package org.ns.longhttp.handler;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import org.ns.longhttp.ResponseUtil;
import org.ns.longhttp.handler.asynchandler.AsyncResponseHandler;
import org.ns.longhttp.selector.datamapper.DataMappingEntry;
import org.ns.longhttp.selector.datamapper.DataMappingQueue;
import org.ns.longhttp.selector.datamapper.DataResponseEntry;
import org.ns.longhttp.selector.requestmapper.RequestMappingQueue;
import org.ns.longhttp.wrapper.GetRequestWrapper;
import org.ns.longhttp.wrapper.GetResponseWrapper;
import org.ns.longhttp.wrapper.UrlParameterMap;

import java.nio.charset.Charset;
import java.util.List;

/**
 * HTTP 长轮训消息处理器
 */
public class HttpServerReaderHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

    private RequestMappingQueue requestQueue;
    private DataMappingQueue dataqueue;
    private AsyncResponseHandler asyncHandler;

    public HttpServerReaderHandler(RequestMappingQueue requestQueue, DataMappingQueue dataqueue, AsyncResponseHandler asyncHandler) {
        this.requestQueue = requestQueue;
        this.dataqueue = dataqueue;
        this.asyncHandler = asyncHandler;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception {
        String url = getUrl(req.uri());
        HttpMethod method = req.method();

        if (method == HttpMethod.GET) {
            doGet(ctx, req, url); // 客户端获取数据
        } else if (method == HttpMethod.POST) {
            doPost(ctx, req, url);// 给客户端推送数据
        } else {
            // 暂时不支持这类方法
            ResponseUtil.write(ctx, req, HttpResponseStatus.METHOD_NOT_ALLOWED);
        }
    }

    private void doGet(ChannelHandlerContext ctx, FullHttpRequest req, String url) {
        DataMappingEntry dataMappingEntry = dataqueue.getDataMappingEntry(url); // 数据与URL映射实体
        UrlParameterMap parameterMap = new UrlParameterMap(req, Charset.forName("UTF-8"));
        UrlParameterMap.Result idValue = parameterMap.getParameterOrCookieValue("id");
        long id = idValue.getLong(dataMappingEntry.getMaxId()); // 获取ID
        GetRequestWrapper requestWrapper = new GetRequestWrapper(req, ctx, url, id);
        if (dataMappingEntry.hasNew(id)) { // 存在新的直接返回
            List<DataResponseEntry> dataResponseEntrys = dataMappingEntry.getDataResponseEntrys(id);
            if (dataResponseEntrys.size() > 0) {
                GetResponseWrapper responseWrapper = new GetResponseWrapper(dataResponseEntrys);
                requestWrapper.write(responseWrapper);
                return;
            }
        }
        requestQueue.add(requestWrapper); // 请求队列

    }

    private void doPost(ChannelHandlerContext ctx, FullHttpRequest req, String url) {
        ByteBuf content = req.content();
        byte[] data = new byte[content.readableBytes()];
        content.readBytes(data);
        String dataJson = new String (data, Charset.forName("UTF-8"));

        try {
            DataResponseEntry dataResponseEntry = DataResponseEntry.newInstance(dataJson);
            if (dataResponseEntry == null) {
                ResponseUtil.write(ctx, req, HttpResponseStatus.NO_CONTENT);
            } else {
                dataqueue.put(url, dataResponseEntry); // 数据队列
                asyncHandler.add(url);
                ResponseUtil.write(ctx, req, HttpResponseStatus.OK);
            }
        } catch (Exception e) {
            e.printStackTrace();
            ResponseUtil.write(ctx, req, new HttpResponseStatus(500, e.getMessage()));
        }
    }

    private String getUrl(String uri) {
        int index = uri.indexOf("?");
        if (index == -1) {
            return uri;
        } else {
            return uri.substring(0, index);
        }
    }

}
